package xiaojian.toolkit.netty.handler.codec.tlv;

import java.util.UUID;

import com.google.common.primitives.Bytes;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import xiaojian.toolkit.bean.tlv.TLVSignal;
import xiaojian.toolkit.bean.utils.CodecUtils;
import xiaojian.toolkit.util.ExceptionUtils;

@ChannelHandler.Sharable
public class NettyMixedTcpEncoder extends MessageToByteEncoder {
	private static final Logger logger = LoggerFactory
			.getLogger(NettyMixedTcpEncoder.class);

	private CodecUtils tlvEncoder;

	@Override
	public void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)
			throws Exception {
		if (msg instanceof TLVSignal) {
			if (logger.isDebugEnabled()) {
				logger.debug(
						"encoding saipSignal/tlvSignal {} to wrappedBuffer ...",
						msg);
			}
			byte[] bytes = tlvEncoder.encode(msg);
			out.writeBytes(bytes);
		} else if (msg instanceof JSONObject) {
			try {
				final UUID id = UUID.fromString(((JSONObject) msg)
						.getString("_transactionId"));
				if (logger.isDebugEnabled()) {
					logger.debug("encoding JSONObject {} to wrappedBuffer", msg);
				}
				if (null != id) {
					final String jsonString = JSON.toJSONString(msg);
					final byte[] jsonBytes = jsonString.getBytes("UTF-8");
					out.writeBytes(Bytes.concat(this.tlvEncoder
							.genHeaderToBytes((byte) 100, id, 1,
									jsonBytes.length), jsonBytes));
				} else {
					if (logger.isWarnEnabled()) {
						logger.warn("{} is json but missing _transactionId",
								msg);
					}
				}
			} catch (Exception e) {
				logger.error("exception when encode JSONObject {}, detail: {}",
						msg, ExceptionUtils.exception2detail(e));
			}
		} else {
			if (logger.isDebugEnabled()) {
				logger.debug("{} is not a xipSignal/tlvSignal/json", msg);
			}
		}
	}

	public void setTlvEncoder(CodecUtils tlvEncoder) {
		this.tlvEncoder = tlvEncoder;
	}
}
